package com.ddd.utils;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class JedisUtil {
    /**
     * 声明连接池对象，声明成static类型，保证项目在启动时，就加载连接池
     */
    private static JedisPool pool;

    /***
     * Jedis连接池连接的最大值
     */
    private static int maxTotal = 20;

    /***
     * Jedis连接池中最大的空闲连接数
     */
    private static int maxIdel = 20;

    /***
     * Jedis连接池中最小的空闲连接数
     */
    private static int miniIdel = 10;

    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.password}")
    private String password;
    @Value("${spring.redis.database}")
    private int database;

    /**
     * 初始化Jedis连接池
     */
//    public static void initJedisPool() {
//
//        JedisPoolConfig config = new JedisPoolConfig();
//        config.setMaxTotal(maxTotal);
//        config.setMaxIdle(maxIdel);
//        config.setMinIdle(miniIdel);
//
//        //创建连接池，超时时间为2秒
//        pool = new JedisPool(config, ip, port, 2000);
//    }

    /**
     * 初始化Jedis连接池
     */
    @PostConstruct
    public void initialize() {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(maxTotal);
        config.setMaxIdle(maxIdel);
        config.setMinIdle(miniIdel);
        pool = new JedisPool(config, host, port, 2000, password, database);
    }

    /**
     * 静态代码块初始化连接池
     */
//    static {
//        initJedisPool();
//    }

    /**
     * 从连接池中获取Jedis连接
     *
     * @return jedis连接
     */
    public static Jedis getJedis() {
        return pool.getResource();
    }


    /**
     * 回收jedis连接
     *
     * @param jedis 需要关闭的jedis连接对象
     */
    public static void returnJedis(Jedis jedis) {
        //3.0之前所用的归还连接方式，现在使用close
        // pool.returnResource(jedis);
        if (null != jedis) {
            jedis.close();
        }
    }


    /***
     * 获取锁
     * @param key
     * @return 成功返回OK，失败返回null
     */
    public static boolean getLock(String key, String value, String nxxx, String expx, long time) {

        Jedis jedis = null;
        try {
            jedis = getJedis();
            String result = jedis.set(key, value, nxxx, expx, time);
            if (result != null && "OK".equals(result))
                return true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            returnJedis(jedis);
        }
        return false;
    }

    /***
     * 获取String类型的值
     * @return
     */
    public static void unLock(List<String> key, List<String> value) {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
            jedis.eval(script, key, value);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            returnJedis(jedis);
        }
    }

    public static void watchDog(String key, String value) {
        //开一个守护线程延长锁的过期时间
        Thread thread = new Thread(() -> {
            while (true) {
                Jedis jedis = getJedis();
                try {
                    TimeUnit.SECONDS.sleep(1);
                    System.out.println("守护线程延长锁的过期时间1s");
                    jedis.setex(key, 1, value);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    if (jedis != null) {
                        jedis.close();
                    }
                }
            }
        });
        thread.setDaemon(true);
        thread.start();
    }
}
